package com.hotClass;

import com.classLoader.HotCLassLoaderTest;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.util.Arrays;
import java.util.List;

public class Singleton {

    private static Object single = null;
    private static Class singleClass = Singleton.class;

    //newInstance()方法里调用的是默认的无参构造器，因此不能加private
//    private Singleton() {}
    public static synchronized Object getInstance() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        if (single == null) {
            single = singleClass.newInstance();
        }
        return single;
    }

    /**
     * 程序运行时修改下面的打印内容并保存，HotClassMonitor监听到文件变化，进行热加载
     */
    public void testPrint() {
        System.out.println("hello11");
    }

    /**
     * 热加载监听器
     */
    public static class HotClassMonitor {

        private static String hotFilePath = "D:\\DownLoadProject\\LearnJVM\\src\\com\\hotClass\\Singleton.java"; //本文件路径
        private final static String classFilePath = "D:\\DownLoadProject\\LearnJVM\\out\\production\\LearnJVM\\"; //编译后classpath路径

        public static void startMonitoring() {
            //开启一个后台线程监听文件是否被修改
            new Thread(() -> {
                long lastModified = new File(hotFilePath).lastModified();
                while (true) {
                    try {
                        Thread.sleep(1000);
                        long now = new File(hotFilePath).lastModified();
                        if (now != lastModified) {
                            System.out.println("文件已被修改，进行热加载");
                            lastModified = now;
                            //若修改，则重新加载类
                            reloadClass();
                            single = null;//将对象设置为null，另外一个线程执行方法时，会自动获取最新的对象
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

            }).start();
        }

        private static void reloadClass() {
            //生成class文件
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

            StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);
            Iterable<? extends JavaFileObject> iterable = standardFileManager.getJavaFileObjects(new File(hotFilePath));
            // 编译参数 把结果文件生成与原class文件同一个目录 覆盖原文件
            List<String> options = Arrays.asList("-d", classFilePath);
            // 创建一个编译任务
            JavaCompiler.CompilationTask task = compiler.getTask(null, standardFileManager, null, options, null, iterable);
            //JavaCompiler.CompilationTask 实现了 Callable 接口
            Boolean result = task.call();
            System.out.println(result ? "成功" : "失败");
            try {
                //获取对象的class对象
                singleClass = new HotCLassLoaderTest.HotClassLoader().loadClass("com.hotClass.Singleton");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}
